/*
*Copyright 2021-2023 NERCIS
*
*Licensed under the Apache License, Version 2.0 (the "License");
*you may not use this file except in compliance with the License.
*You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*Unless required by applicable law or agreed to in writing, software
*distributed under the License is distributed on an "AS IS" BASIS,
*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*See the License for the specific language governing permissions and
*limitations under the License.
*/

package cn.ac.nercis.pes.community.component.dialog;

import cn.ac.nercis.pes.community.support.event.CommonCallback;
import cn.ac.nercis.pes.community.utils.GuiStore;
import cn.ac.nercis.pes.community.utils.IconUtils;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.Window;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;

import java.util.Objects;

/**
 * 页面弹出框组件
 * @author zpy
 * @version v1.0.0
 */
public class PageDialog {
    private final Dialog<Boolean> dialog;
    private final PesDialogPane layout;

    @Getter
    @Setter
    private String icon;
    @Getter
    @Setter
    private String title;
    @Getter
    @Setter
    private Node content;
    @Getter
    @Setter
    private Boolean showClose;
    @Getter
    @Setter
    private Boolean overlayClose;
    @Getter
    @Setter
    private String yesText;
    @Getter
    @Setter
    private String noText;
    private CommonCallback callback;
    private CommonCallback onClose;

    public PageDialog(boolean showActions) {
        layout = new PesDialogPane(showActions);
        dialog = new Dialog<>();
        dialog.initStyle(StageStyle.TRANSPARENT);
        dialog.setResizable(true);
        overlayClose = false;
        showClose = true;
        yesText = "保存";
        noText = "关闭";
    }

    private PageDialog(Builder builder){
        this(builder.showActions);
        overlayClose = builder.overlayClose;
        showClose = builder.showClose;
        icon = builder.icon;
        title = builder.title;
        content = builder.content;
        if(Objects.nonNull(builder.owner)){
            dialog.initOwner(builder().owner);
        }

        dialog.setTitle(title);
    }

    public StackPane getDialogContainer(){
        return this.layout.getDialogRoot();
    }

    public void show(){
        show(null);
    }

    public void show(CommonCallback callback){
        this.render();
        this.callback = callback;
        this.dialog.show();
        if(this.layout.getScene().getWindow() instanceof Stage stage && stage.getIcons().isEmpty()){
            stage.getIcons().addAll(GuiStore.readIcons());
        }
    }

    public void setOnClose(CommonCallback closeEvent){
        this.onClose = closeEvent;
    }

    public void close(){
        this.dialog.setResult(false);
        this.dialog.close();
        if(Objects.nonNull(this.onClose)){
            this.onClose.action();
        }
    }

    private void render(){
        this.renderTitle();
        this.layout.setBody(this.content);
        if(this.layout.showActions){
            this.renderAction();
        }
        this.dialog.setDialogPane(layout);
        this.layout.getScene().setFill(Color.TRANSPARENT);
    }

    private void renderTitle(){
        var pane = new HBox();
        pane.setAlignment(Pos.CENTER_LEFT);
        pane.setPadding(new Insets(0,10,0,20));
        var titleLabel = new Label(this.title);
        titleLabel.getStyleClass().add("page-dialog-title");
        if (StringUtils.isNotEmpty(this.icon)) {
            titleLabel.setGraphic(IconUtils.getGlyph(this.icon,"page-dialog-icon"));
            titleLabel.setGraphicTextGap(5);
        }
        pane.getChildren().add(titleLabel);
        if (showClose) {
            var closeBox = new HBox();
            closeBox.setAlignment(Pos.CENTER_RIGHT);
            HBox.setHgrow(closeBox, Priority.SOMETIMES);
            var closeButton = new Button();
            closeButton.setOnAction(event -> this.close());
            closeButton.getStyleClass().add("dialog-window-btn");
            closeButton.setGraphic(IconUtils.getGlyph("win-close","dialog-title-bar-close-icon"));
            closeButton.setTooltip(new Tooltip("关闭"));
            closeBox.getChildren().add(closeButton);
            pane.getChildren().add(closeBox);
        }
        pane.getStyleClass().add("pes-layout-heading");
        layout.setHeading(pane);
    }

    private void renderAction(){
        layout.setYesText(this.yesText);
        layout.getYesButton().setOnAction(event -> {
            if(Objects.nonNull(callback)){
                callback.action();
            }
        });
        layout.setNoText(this.noText);
        layout.getNoButton().setOnAction(event -> this.close());
    }

    public static Builder builder(){
        return new Builder();
    }

    public static final class Builder {
        private String icon;
        private String title;
        private Node content;
        private Window owner;
        private Boolean showActions = true;
        private Boolean showClose = true;
        private Boolean overlayClose = false;

        public Builder withIcon(String icon){
            this.icon = icon;
            return this;
        }

        public Builder withTitle(String title){
            this.title = title;
            return this;
        }

        public Builder withContent(Node content){
            this.content = content;
            return this;
        }

        public Builder withOwner(Window owner) {
            this.owner = owner;
            return this;
        }

        public Builder withShowActions(Boolean showActions) {
            this.showActions = showActions;
            return this;
        }

        public Builder withShowClose(Boolean showClose) {
            this.showClose = showClose;
            return this;
        }

        public Builder withOverlayClose(Boolean overlayClose) {
            this.overlayClose = overlayClose;
            return this;
        }

        public PageDialog build() {
            return new PageDialog(this);
        }
    }
}